<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <svg width="600" height="600"></svg>
  </body>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script>
    const data = [
      {
        year: 2011,
        entities: [
          { name: 'A', value: 100 },
          { name: 'B', value: 50 },
          { name: 'C', value: 60 },
          { name: 'D', value: 20 },
          { name: 'E', value: 10 },
        ],
      },
      {
        year: 2012,
        entities: [
          { name: 'A', value: 110 },
          { name: 'B', value: 56 },
          { name: 'C', value: 80 },
          { name: 'D', value: 18 },
          { name: 'E', value: 20 },
        ],
      },
      {
        year: 2013,
        entities: [
          { name: 'A', value: 105 },
          { name: 'B', value: 78 },
          { name: 'C', value: 60 },
          { name: 'D', value: 21 },
          { name: 'E', value: 10 },
        ],
      },
      {
        year: 2014,
        entities: [
          { name: 'A', value: 120 },
          { name: 'B', value: 80 },
          { name: 'C', value: 60 },
          { name: 'D', value: 21 },
          { name: 'E', value: 5 },
        ],
      },
      {
        year: 2015,
        entities: [
          { name: 'A', value: 115 },
          { name: 'B', value: 62 },
          { name: 'C', value: 60 },
          { name: 'D', value: 19 },
          { name: 'E', value: 30 },
        ],
      },
      {
        year: 2016,
        entities: [
          { name: 'A', value: 90 },
          { name: 'B', value: 93 },
          { name: 'C', value: 60 },
          { name: 'D', value: 16 },
          { name: 'E', value: 50 },
        ],
      },
      {
        year: 2017,
        entities: [
          { name: 'A', value: 110 },
          { name: 'B', value: 71 },
          { name: 'C', value: 60 },
          { name: 'D', value: 20 },
          { name: 'E', value: 90 },
        ],
      },
      {
        year: 2018,
        entities: [
          { name: 'A', value: 105 },
          { name: 'B', value: 45 },
          { name: 'C', value: 60 },
          { name: 'D', value: 20 },
          { name: 'E', value: 120 },
        ],
      },
    ]

    // 设定与矩形和字体相关的样式
    const rect = { height: 40, marginV: 10, marginH: 10, marginT: 40 }
    const font = { height: 20, margin: 35 }

    const svg = d3.select('svg').append('g')
    const scale = d3.scaleLinear().domain([10, 120]).range([40, 360])

    // 每次取出一个元素 依数值大小将 entities 进行排序
    let index = 0
    let dataEntry = data[index]
    let dataValue = dataEntry['entities'].sort((x, y) => y.value - x.value)

    // 最大长度，即最后一个矩形的底边 y 值
    const maxHeight =
      (rect.marginV + rect.height) * (dataValue.length - 1) + rect.marginT
    // 右下角年份
    let comment = svg
      .append('text')
      .attr('x', 300)
      .attr('y', maxHeight)
      .attr('fill', 'grey')
      .text(dataEntry.year)
      .style('font-size', '40')
    //绑定该年数据
    const groups = svg
      .selectAll('g')
      .data(dataValue)
      .enter()
      .append('g')
      .style('cursor', 'pointer')
      .on('click', () => update(++index % data.length))
    // 名称标签 以及矩形
    let labels = groups
      .append('text')
      .text((d) => d.name)
      .attr('x', rect.marginH)
      .style('font-size', `${font.height}px`)
    let rects = groups
      .append('rect')
      .attr('x', rect.marginH + font.margin)
      .attr('height', rect.height)
      .attr('fill', (d) => (d.name == 'E' ? 'red' : 'grey'))

    svg
      .append('g')
      .attr(
        'transform',
        `translate(${rect.marginH}, ${maxHeight + rect.height + rect.marginV})`
      )
      .call(d3.axisBottom(scale))

    function updateElements() {
      labels
        .data(dataValue, (d) => d.name)
        .transition()
        .duration(600)
        .attr(
          'y',
          (_, i) =>
            (rect.marginV + rect.height) * i + rect.marginT + rect.height / 2
        )

      rects
        .data(dataValue, (d) => d.name)
        .transition()
        .duration(600)
        .attr('y', (_, i) => (rect.marginV + rect.height) * i + rect.marginT)
        .attr('width', (d) => scale(d.value))
    }

    updateElements()

    function update(i) {
      dataEntry = data[i]
      dataValue = dataEntry['entities'].sort((x, y) => y.value - x.value)

      comment.text(dataEntry.year)
      updateElements()
    }

    // setInterval(() => update(++index % data.length), 700)
  </script>
</html>
